package com.qulei.demo.db.utils;

import java.lang.reflect.Field;
import java.sql.Blob;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import android.content.ContentValues;
import android.database.Cursor;

import com.qulei.demo.db.annotation.Column;
import com.qulei.demo.db.annotation.Id;
import com.qulei.demo.db.annotation.Table;

public class TableHelper<T> {

	public static final String TAG = "qulei";

	public static final int CONTENT_VALUES_CREATE = 1001;
	public static final int CONTENT_VALUES_UPDATE = 1002;

	private Class<T> mClass = null;

	private List<Field> listFields = null;

	public TableHelper(Class<T> clazz) {
		this.mClass = clazz;
		listFields = getAllFields();
	}

	public String getTableName() {
		if (mClass.isAnnotationPresent(Table.class)) {// 判断是否为注解类
			Table table = (Table) mClass.getAnnotation(Table.class);
			return table.name();
		} else {
			return null;
		}
	}

	private List<Field> getAllFields() {
		return joinFields(mClass.getDeclaredFields(), mClass.getSuperclass()
				.getDeclaredFields());
	}

	// 合并Field数组并去重,并实现过滤掉非Column字段,和实现Id放在首字段位置功能
	private List<Field> joinFields(Field[] fields1, Field[] fields2) {
		Map<String, Field> map = new LinkedHashMap<String, Field>();
		for (Field field : fields1) {

			if (!field.isAnnotationPresent(Column.class)) { // 过滤掉非Column定义的字段
				continue;
			}
			Column column = (Column) field.getAnnotation(Column.class);
			map.put(column.name(), field);
		}
		for (Field field : fields2) {
			if (!field.isAnnotationPresent(Column.class)) { // 过滤掉非Column定义的字段
				continue;
			}
			Column column = (Column) field.getAnnotation(Column.class);
			if (!map.containsKey(column.name())) {
				map.put(column.name(), field);
			}
		}

		if (map.size() > 0) {
			List<Field> list = new ArrayList<Field>();
			for (String key : map.keySet()) {
				Field tempField = map.get(key);
				if (tempField.isAnnotationPresent(Id.class)) { // 如果是Id则放在首位置.
					list.add(0, tempField);
				} else {
					list.add(tempField);
				}
			}
			return list;
		} else {
			return null;
		}
	}

	private String getColumnType(Class<?> fieldType) {
		if (String.class == fieldType) {
			return "TEXT";
		}
		if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {
			return "INTEGER";
		}
		if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
			return "BIGINT";
		}
		if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
			return "FLOAT";
		}
		if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {
			return "INT";
		}
		if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {
			return "DOUBLE";
		}
		if (Blob.class == fieldType) {
			return "BLOB";
		}

		return "TEXT";
	}

	public String dropTable() {
		String tableName = getTableName();
		if (tableName != null) {
			return "DROP TABLE IF EXISTS " + tableName;
		} else {
			return null;
		}

	}

	public String createTable() {
		String tableName = getTableName();
		if (tableName != null) {
			if (listFields != null && listFields.size() > 0) {
				StringBuilder sb = new StringBuilder();
				sb.append("CREATE TABLE ").append(tableName).append(" (");
				for (Field field : listFields) {
					if (!field.isAnnotationPresent(Column.class)) {
						continue;
					}
					Column column = (Column) field.getAnnotation(Column.class);
					String columnType = "";
					if (column.type().equals(""))
						columnType = getColumnType(field.getType());
					else {
						columnType = column.type();
					}
					sb.append(column.name() + " " + columnType);
					if (column.length() != 0) {
						sb.append("(" + column.length() + ")");
					}
					if (((field.isAnnotationPresent(Id.class)) && (field
							.getType() == Integer.TYPE))
							|| (field.getType() == Integer.class))
						sb.append(" primary key autoincrement");
					else if (field.isAnnotationPresent(Id.class)) {
						sb.append(" primary key");
					}
					sb.append(", ");
				}
				sb.delete(sb.length() - 2, sb.length() - 1);
				sb.append(")");
				return sb.toString();
			} else {
				return null;
			}
		} else {
			return null;
		}
	}

	public ContentValues convertObjectToContentValues(T t, int type)
			throws IllegalArgumentException, IllegalAccessException {

		ContentValues values = null;

		if (mClass.isAnnotationPresent(Table.class)) {// 判断是否为注解类
			values = new ContentValues();
			if (listFields != null && listFields.size() > 0) {
				for (Field field : listFields) {
					if (!field.isAnnotationPresent(Column.class)) {
						continue;
					}
					Column column = (Column) field.getAnnotation(Column.class);
					field.setAccessible(true);
					Object fieldValue;
					fieldValue = field.get(t);
					if (fieldValue == null)
						continue;
					if ((CONTENT_VALUES_CREATE == type)
							&& (field.isAnnotationPresent(Id.class))) {
						continue;
					}
					values.put(column.name(), fieldValue.toString());
				}

				return values;
			} else {
				return null;
			}

		} else {
			return null;
		}

	}

	public T convertCursorToObject(Cursor cursor)
			throws IllegalAccessException, InstantiationException {
		if (listFields != null && listFields.size() > 0) {
			T entity = mClass.newInstance();
			for (Field field : listFields) {
				Column column = null;
				if (field.isAnnotationPresent(Column.class)) {
					column = (Column) field.getAnnotation(Column.class);
					field.setAccessible(true);
					Class<?> fieldType = field.getType();
					int c = cursor.getColumnIndex(column.name());
					if (c < 0) {
						continue; // 如果不存则循环下个属性值
					} else if ((Integer.TYPE == fieldType)
							|| (Integer.class == fieldType)) {
						field.set(entity, cursor.getInt(c));
					} else if (String.class == fieldType) {
						field.set(entity, cursor.getString(c));
					} else if ((Long.TYPE == fieldType)
							|| (Long.class == fieldType)) {
						field.set(entity, Long.valueOf(cursor.getLong(c)));
					} else if ((Float.TYPE == fieldType)
							|| (Float.class == fieldType)) {
						field.set(entity, Float.valueOf(cursor.getFloat(c)));
					} else if ((Short.TYPE == fieldType)
							|| (Short.class == fieldType)) {
						field.set(entity, Short.valueOf(cursor.getShort(c)));
					} else if ((Double.TYPE == fieldType)
							|| (Double.class == fieldType)) {
						field.set(entity, Double.valueOf(cursor.getDouble(c)));
					} else if (Blob.class == fieldType) {
						field.set(entity, cursor.getBlob(c));
					} else if (Character.TYPE == fieldType) {
						String fieldValue = cursor.getString(c);
						if ((fieldValue != null) && (fieldValue.length() > 0)) {
							field.set(entity,
									Character.valueOf(fieldValue.charAt(0)));
						}
					}
				}
			}
			return (T) entity;
		} else {
			return null;
		}
	}

}
